home *** CD-ROM | disk | FTP | other *** search
- #include <Sound.h>
-
- /* The following limits are adequate for displays up to 200x200 */
- #define MAX_MAZE_SIZE_X 205
- #define MAX_MAZE_SIZE_Y 145
- #define LOGOSIZE 20
-
- #define MOVE_LIST_SIZE (MAX_MAZE_SIZE_X * MAX_MAZE_SIZE_Y)
-
- #define WALL_TOP 0x8000
- #define WALL_RIGHT 0x4000
- #define WALL_BOTTOM 0x2000
- #define WALL_LEFT 0x1000
-
- #define DOOR_IN_TOP 0x0800
- #define DOOR_IN_RIGHT 0x0400
- #define DOOR_IN_BOTTOM 0x0200
- #define DOOR_IN_LEFT 0x0100
- #define DOOR_IN_ANY 0x0F00
-
- #define DOOR_OUT_TOP 0x0080
- #define DOOR_OUT_RIGHT 0x0040
- #define DOOR_OUT_BOTTOM 0x0020
- #define DOOR_OUT_LEFT 0x0010
-
- #define START_SQUARE 0x0002
- #define END_SQUARE 0x0001
-
- #define SQ_SIZE_X 3
- #define SQ_SIZE_Y 3
-
- long get_random(long);
- long choose_door();
- long backup();
- long draw_solid_square();
- //static long randnum[NUM_RANDOM];
- //Rect pwrect;
-
- struct my_mem {
- unsigned long maze[MAX_MAZE_SIZE_X][MAX_MAZE_SIZE_Y];
- struct {
- unsigned char x;
- unsigned char y;
- unsigned char dir;
- } move_list[MOVE_LIST_SIZE],
- save_path[MOVE_LIST_SIZE],
- path[MOVE_LIST_SIZE];
- };
- struct my_mem *memP;
-
- PixPatHandle pph0, pph1, pph2;
-
- long maze_size_x, maze_size_y, border_x, border_y;
- long sqnum, cur_sq_x, cur_sq_y, path_length;
- long start_x, start_y, start_dir, end_x, end_y, end_dir;
- //static long maze_restart_flag, lockcount, colorwindows, random_index;
- static long logo_x, logo_y;
-
- extern CWindowPtr gPictureWindow;
- extern RGBColor myBlack, myWhite, myGray;
- extern Boolean gDone;
- extern Handle gSolvedSndH;
-
- /* main module */
- rinth()
- {
-
- if ((memP = (struct my_mem *)NewPtr(sizeof(struct my_mem))) == nil)
- return;
-
- if ((pph0 = GetPixPat(128)) == 0)
- return;
- if ((pph1 = GetPixPat(129)) == 0)
- return;
- if ((pph2 = GetPixPat(130)) == 0)
- return;
-
- set_maze_sizes();
-
- initialize_maze();
-
- ErasePort(gPictureWindow, gPictureWindow->portRect);
-
- RGBBackColor(&myBlack);
- RGBForeColor(&myGray);
- draw_maze_border();
-
- create_maze();
-
- if (!gDone)
- solve_maze();
-
- if (!gDone)
- SndPlay(0, gSolvedSndH, 0);
-
- DisposePtr((Ptr)memP);
- DisposePixPat(pph0);
- DisposePixPat(pph1);
- DisposePixPat(pph2);
-
- } /* end of main() */
-
-
- set_maze_sizes()
- {
- maze_size_x = MAX_MAZE_SIZE_X;
- maze_size_y = MAX_MAZE_SIZE_Y;
-
- border_x = 1;
- border_y = 1;
-
- } /* end of set_maze_sizes */
-
-
- initialize_maze() /* draw the surrounding wall and start/end squares */
- {
- long i, j, wall;
-
- /* initialize all squares */
- for ( i=0; i<maze_size_x; i++) {
- for ( j=0; j<maze_size_y; j++) {
- memP->maze[i][j] = 0;
- }
- }
-
- /* top wall */
- for ( i=0; i<maze_size_x; i++ ) {
- memP->maze[i][0] |= WALL_TOP;
- }
-
- /* right wall */
- for ( j=0; j<maze_size_y; j++ ) {
- memP->maze[maze_size_x-1][j] |= WALL_RIGHT;
- }
-
- /* bottom wall */
- for ( i=0; i<maze_size_x; i++ ) {
- memP->maze[i][maze_size_y-1] |= WALL_BOTTOM;
- }
-
- /* left wall */
- for ( j=0; j<maze_size_y; j++ ) {
- memP->maze[0][j] |= WALL_LEFT;
- }
-
- /* set start square */
- wall = get_random(4);
- switch (wall) {
- case 0:
- i = get_random(maze_size_x);
- j = 0L;
- break;
- case 1:
- i = maze_size_x - 1;
- j = get_random(maze_size_y);
- break;
- case 2:
- i = get_random(maze_size_x);
- j = maze_size_y - 1;
- break;
- case 3:
- i = 0L;
- j = get_random(maze_size_y);
- break;
- }
- memP->maze[i][j] |= START_SQUARE;
- memP->maze[i][j] |= ( DOOR_IN_TOP >> wall );
- memP->maze[i][j] &= ~( WALL_TOP >> wall );
- cur_sq_x = i;
- cur_sq_y = j;
- start_x = i;
- start_y = j;
- start_dir = wall;
- sqnum = 0;
-
- /* set end square */
- wall = (wall + 2)%4;
- switch (wall) {
- case 0:
- i = get_random(maze_size_x);
- j = 0L;
- break;
- case 1:
- i = maze_size_x - 1;
- j = get_random(maze_size_y);
- break;
- case 2:
- i = get_random(maze_size_x);
- j = maze_size_y - 1;
- break;
- case 3:
- i = 0L;
- j = get_random(maze_size_y);
- break;
- }
- memP->maze[i][j] |= END_SQUARE;
- memP->maze[i][j] |= ( DOOR_OUT_TOP >> wall );
- memP->maze[i][j] &= ~( WALL_TOP >> wall );
- end_x = i;
- end_y = j;
- end_dir = wall;
-
-
- /* set logo */
- if ( (maze_size_x > 15) && (maze_size_y > 15) ) {
- logo_x = get_random(maze_size_x - LOGOSIZE - 6) + 3;
- logo_y = get_random(maze_size_y - LOGOSIZE - 6) + 3;
-
- for (i=0; i<LOGOSIZE; i++) {
- for (j=0; j<LOGOSIZE; j++) {
- memP->maze[logo_x + i][logo_y + j] |= DOOR_IN_TOP;
- }
- }
- }
- else
- logo_y = logo_x = -1;
- }
-
-
- create_maze() /* create a maze layout given the intiialized maze */
- {
- long i, newdoor;
-
- do {
- memP->move_list[sqnum].x = cur_sq_x;
- memP->move_list[sqnum].y = cur_sq_y;
- memP->move_list[sqnum].dir = newdoor;
- while ( ( newdoor = choose_door() ) == -1 ) { /* pick a door */
- if ( backup() == -1 ) { /* no more doors ... backup */
- return; /* done ... return */
- }
- }
-
- /* mark the out door */
- memP->maze[cur_sq_x][cur_sq_y] |= ( DOOR_OUT_TOP >> newdoor );
-
- switch (newdoor) {
- case 0: cur_sq_y--;
- break;
- case 1: cur_sq_x++;
- break;
- case 2: cur_sq_y++;
- break;
- case 3: cur_sq_x--;
- break;
- }
- sqnum++;
-
- /* mark the in door */
- memP->maze[cur_sq_x][cur_sq_y] |= ( DOOR_IN_TOP >> ((newdoor+2)%4) );
-
- /* if end square set path length and save path */
- if ( memP->maze[cur_sq_x][cur_sq_y] & END_SQUARE ) {
- path_length = sqnum;
- for ( i=0; i<path_length; i++) {
- memP->save_path[i].x = memP->move_list[i].x;
- memP->save_path[i].y = memP->move_list[i].y;
- memP->save_path[i].dir = memP->move_list[i].dir;
- }
- }
-
- } while (1);
-
- } /* end of create_maze() */
-
-
- long
- choose_door() /* pick a new path */
- {
- long candidates[3];
- long num_candidates;
- long tics;
-
- num_candidates = 0L;
-
- if (gDone)
- return(-1);
-
- topwall:
- /* top wall */
- if ( memP->maze[cur_sq_x][cur_sq_y] & DOOR_IN_TOP )
- goto rightwall;
- if ( memP->maze[cur_sq_x][cur_sq_y] & DOOR_OUT_TOP )
- goto rightwall;
- if ( memP->maze[cur_sq_x][cur_sq_y] & WALL_TOP )
- goto rightwall;
- if ( memP->maze[cur_sq_x][cur_sq_y - 1] & DOOR_IN_ANY ) {
- memP->maze[cur_sq_x][cur_sq_y] |= WALL_TOP;
- memP->maze[cur_sq_x][cur_sq_y - 1] |= WALL_BOTTOM;
- draw_wall(cur_sq_x, cur_sq_y, 0L);
- goto rightwall;
- }
- candidates[num_candidates++] = 0;
-
- rightwall:
- /* right wall */
- if ( memP->maze[cur_sq_x][cur_sq_y] & DOOR_IN_RIGHT )
- goto bottomwall;
- if ( memP->maze[cur_sq_x][cur_sq_y] & DOOR_OUT_RIGHT )
- goto bottomwall;
- if ( memP->maze[cur_sq_x][cur_sq_y] & WALL_RIGHT )
- goto bottomwall;
- if ( memP->maze[cur_sq_x + 1][cur_sq_y] & DOOR_IN_ANY ) {
- memP->maze[cur_sq_x][cur_sq_y] |= WALL_RIGHT;
- memP->maze[cur_sq_x + 1][cur_sq_y] |= WALL_LEFT;
- draw_wall(cur_sq_x, cur_sq_y, 1L);
- goto bottomwall;
- }
- candidates[num_candidates++] = 1;
-
- bottomwall:
- /* bottom wall */
- // Delay(1, &tics);
- if ( memP->maze[cur_sq_x][cur_sq_y] & DOOR_IN_BOTTOM )
- goto leftwall;
- if ( memP->maze[cur_sq_x][cur_sq_y] & DOOR_OUT_BOTTOM )
- goto leftwall;
- if ( memP->maze[cur_sq_x][cur_sq_y] & WALL_BOTTOM )
- goto leftwall;
- if ( memP->maze[cur_sq_x][cur_sq_y + 1] & DOOR_IN_ANY ) {
- memP->maze[cur_sq_x][cur_sq_y] |= WALL_BOTTOM;
- memP->maze[cur_sq_x][cur_sq_y + 1] |= WALL_TOP;
- draw_wall(cur_sq_x, cur_sq_y, 2L);
- goto leftwall;
- }
- candidates[num_candidates++] = 2;
-
- leftwall:
- /* left wall */
- if ( memP->maze[cur_sq_x][cur_sq_y] & DOOR_IN_LEFT )
- goto donewall;
- if ( memP->maze[cur_sq_x][cur_sq_y] & DOOR_OUT_LEFT )
- goto donewall;
- if ( memP->maze[cur_sq_x][cur_sq_y] & WALL_LEFT )
- goto donewall;
- if ( memP->maze[cur_sq_x - 1][cur_sq_y] & DOOR_IN_ANY ) {
- memP->maze[cur_sq_x][cur_sq_y] |= WALL_LEFT;
- memP->maze[cur_sq_x - 1][cur_sq_y] |= WALL_RIGHT;
- draw_wall(cur_sq_x, cur_sq_y, 3L);
- goto donewall;
- }
- candidates[num_candidates++] = 3;
-
- donewall:
- if (num_candidates == 0)
- return ( -1 );
- if (num_candidates == 1)
- return ( candidates[0] );
- return ( candidates[ get_random(num_candidates) ] );
-
- } /* end of choose_door() */
-
-
- long
- backup() /* back up a move */
- {
-
- // HandleEvent();
- if (gDone)
- return(-1);
-
- sqnum--;
- cur_sq_x = memP->move_list[sqnum].x;
- cur_sq_y = memP->move_list[sqnum].y;
- return ( sqnum );
- } /* end of backup() */
-
-
- draw_maze_border() /* draw the maze outline */
- {
- long i, j;
- PicHandle picH;
- Rect r;
-
-
- for ( i=0; i<maze_size_x; i++) {
- if ( memP->maze[i][0] & WALL_TOP ) {
- MoveTo(border_x + SQ_SIZE_X * i, border_y);
- LineTo(border_x + SQ_SIZE_X * (i+1), border_y);
- // pw_vector(gfx->gfx_pixwin,
- // border_x + SQ_SIZE_X * i,
- // border_y,
- // border_x + SQ_SIZE_X * (i+1),
- // border_y,
- // PIX_SRC, 1);
- }
- if ((memP->maze[i][maze_size_y - 1] & WALL_BOTTOM)) {
- MoveTo(border_x + SQ_SIZE_X * i, border_y + SQ_SIZE_Y * (maze_size_y));
- LineTo(border_x + SQ_SIZE_X * (i+1), border_y + SQ_SIZE_Y * (maze_size_y));
- // pw_vector(gfx->gfx_pixwin,
- // border_x + SQ_SIZE_X * i,
- // border_y + SQ_SIZE_Y * (maze_size_y),
- // border_x + SQ_SIZE_X * (i+1),
- // border_y + SQ_SIZE_Y * (maze_size_y),
- // PIX_SRC, 1);
- }
- }
- for ( j=0; j<maze_size_y; j++) {
- if ( memP->maze[maze_size_x - 1][j] & WALL_RIGHT ) {
- MoveTo(border_x + SQ_SIZE_X * maze_size_x, border_y + SQ_SIZE_Y * j);
- LineTo(border_x + SQ_SIZE_X * maze_size_x, border_y + SQ_SIZE_Y * (j+1));
- // pw_vector(gfx->gfx_pixwin,
- // border_x + SQ_SIZE_X * maze_size_x,
- // border_y + SQ_SIZE_Y * j,
- // border_x + SQ_SIZE_X * maze_size_x,
- // border_y + SQ_SIZE_Y * (j+1),
- // PIX_SRC, 1);
- }
- if ( memP->maze[0][j] & WALL_LEFT ) {
- MoveTo(border_x, border_y + SQ_SIZE_Y * j);
- LineTo(border_x, border_y + SQ_SIZE_Y * (j+1));
- // pw_vector(gfx->gfx_pixwin,
- // border_x,
- // border_y + SQ_SIZE_Y * j,
- // border_x,
- // border_y + SQ_SIZE_Y * (j+1),
- // PIX_SRC, 1);
- }
- }
-
- picH = GetPicture(128);
- r.top = border_y + SQ_SIZE_Y * logo_y + 2;
- r.left = border_x + SQ_SIZE_X * logo_x + 2;
- r.bottom = r.top + SQ_SIZE_Y * LOGOSIZE - 4;
- r.right = r.left + SQ_SIZE_X * LOGOSIZE - 4;
- DrawPicture(picH, &r);
- ReleaseResource((Handle)picH);
-
- draw_solid_square( start_x, start_y, start_dir, 1L);
- draw_solid_square( end_x, end_y, end_dir, 1L);
-
- } /* end of draw_maze() */
-
-
- draw_wall(i, j, dir) /* draw a single wall */
- long i, j, dir;
- {
- switch (dir) {
- case 0:
- MoveTo(border_x+ SQ_SIZE_X * i, border_y + SQ_SIZE_Y * j);
- LineTo(border_x+ SQ_SIZE_X * (i+1), border_y + SQ_SIZE_Y * j);
- // pw_vector(gfx->gfx_pixwin,
- // border_x + SQ_SIZE_X * i,
- // border_y + SQ_SIZE_Y * j,
- // border_x + SQ_SIZE_X * (i+1),
- // border_y + SQ_SIZE_Y * j,
- // PIX_SRC, 1);
- break;
- case 1:
- MoveTo(border_x+ SQ_SIZE_X * (i+1), border_y + SQ_SIZE_Y * j);
- LineTo(border_x+ SQ_SIZE_X * (i+1), border_y + SQ_SIZE_Y * (j+1));
- // pw_vector(gfx->gfx_pixwin,
- // border_x + SQ_SIZE_X * (i+1),
- // border_y + SQ_SIZE_Y * j,
- // border_x + SQ_SIZE_X * (i+1),
- // border_y + SQ_SIZE_Y * (j+1),
- // PIX_SRC, 1);
- break;
- case 2:
- MoveTo(border_x+ SQ_SIZE_X * i, border_y + SQ_SIZE_Y * (j+1));
- LineTo(border_x+ SQ_SIZE_X * (i+1), border_y + SQ_SIZE_Y * (j+1));
- // pw_vector(gfx->gfx_pixwin,
- // border_x + SQ_SIZE_X * i,
- // border_y + SQ_SIZE_Y * (j+1),
- // border_x + SQ_SIZE_X * (i+1),
- // border_y + SQ_SIZE_Y * (j+1),
- // PIX_SRC, 1);
- break;
- case 3:
- MoveTo(border_x+ SQ_SIZE_X * i, border_y + SQ_SIZE_Y * j);
- LineTo(border_x+ SQ_SIZE_X * i, border_y + SQ_SIZE_Y * (j+1));
- // pw_vector(gfx->gfx_pixwin,
- // border_x + SQ_SIZE_X * i,
- // border_y + SQ_SIZE_Y * j,
- // border_x + SQ_SIZE_X * i,
- // border_y + SQ_SIZE_Y * (j+1),
- // PIX_SRC, 1);
- break;
- }
- } /* end of draw_wall */
-
- long
- get_random(modulo)
- long modulo;
- {
- return ((unsigned long)Random() % modulo);
-
- } /* end of get_random */
-
- long
- draw_solid_square(i, j, dir, color) /* draw a solid square in a square */
- long i, j, dir, color;
- {
- Rect r;
-
- switch (dir) {
- case 0:
- r.left = border_x + 1 + SQ_SIZE_X * i;
- r.top = border_y + SQ_SIZE_Y * j;
- r.right = r.left + SQ_SIZE_X - 1;
- r.bottom = r.top + SQ_SIZE_Y;
- break;
- case 1:
- r.left = border_x + 1 + SQ_SIZE_X * i;
- r.top = border_y + 1 + SQ_SIZE_Y * j;
- r.right = r.left + SQ_SIZE_X;
- r.bottom = r.top + SQ_SIZE_Y - 1;
- break;
- case 2:
- r.left = border_x + 1 + SQ_SIZE_X * i;
- r.top = border_y + 1 + SQ_SIZE_Y * j;
- r.right = r.left + SQ_SIZE_X - 1;
- r.bottom = r.top + SQ_SIZE_Y;
- break;
- case 3:
- r.left = border_x + SQ_SIZE_X * i;
- r.top = border_y + 1 + SQ_SIZE_Y * j;
- r.right = r.left + SQ_SIZE_X;
- r.bottom = r.top + SQ_SIZE_Y - 1;
- break;
- }
-
- switch (color) {
- case 0:
- HLock((Handle)pph1);
- FillCRect(&r, pph1);
- HUnlock((Handle)pph1);
- break;
- case 1:
- HLock((Handle)pph1);
- FillCRect(&r, pph1);
- HUnlock((Handle)pph1);
- break;
- case 2:
- HLock((Handle)pph2);
- FillCRect(&r, pph2);
- HUnlock((Handle)pph2);
- break;
- } /* switch */
-
- } /* end of draw_solid_square() */
-
- solve_maze() /* solve it with graphical feedback */
- {
- int i;
-
- /* plug up the surrounding wall */
- memP->maze[start_x][start_y] |= (WALL_TOP >> start_dir);
- memP->maze[end_x][end_y] |= (WALL_TOP >> end_dir);
-
- /* initialize search path */
- i = 0;
- memP->path[i].x = end_x;
- memP->path[i].y = end_y;
- memP->path[i].dir = -1;
-
- /* do it */
- while (1) {
- if (gDone)
- return;
-
- if ( ++(memP->path[i].dir) >= 4 ) {
- // HandleEvent();
- if (gDone)
- return;
- i--;
- draw_solid_square( (int)(memP->path[i].x), (int)(memP->path[i].y),
- (int)(memP->path[i].dir), 0L);
- }
- else if ( ! (memP->maze[memP->path[i].x][memP->path[i].y] &
- (WALL_TOP >> memP->path[i].dir)) &&
- ( (i == 0) || ( (memP->path[i].dir !=
- (memP->path[i-1].dir+2)%4) ) ) ) {
- enter_square(i);
- i++;
- if ( memP->maze[memP->path[i].x][memP->path[i].y] & START_SQUARE ) {
- return;
- }
- }
- }
- } /* end of solve_maze() */
-
-
- enter_square(n) /* move into a neighboring square */
- int n;
- {
- draw_solid_square( (int)memP->path[n].x, (int)memP->path[n].y,
- (int)memP->path[n].dir, 2L);
-
- memP->path[n+1].dir = -1;
- switch (memP->path[n].dir) {
- case 0: memP->path[n+1].x = memP->path[n].x;
- memP->path[n+1].y = memP->path[n].y - 1;
- break;
- case 1: memP->path[n+1].x = memP->path[n].x + 1;
- memP->path[n+1].y = memP->path[n].y;
- break;
- case 2: memP->path[n+1].x = memP->path[n].x;
- memP->path[n+1].y = memP->path[n].y + 1;
- break;
- case 3: memP->path[n+1].x = memP->path[n].x - 1;
- memP->path[n+1].y = memP->path[n].y;
- break;
- }
-
-
- } /* end of enter_square() */
-